﻿using System;
using System.Linq;
using System.IO.Ports;
using ServiceStack.OrmLite;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
namespace EHR18
{
    public class PLCDevice : SerialDevice
    {
        public static readonly PLCDevice instance = new PLCDevice();
        public IMaster Master { get; set; }
        private PLCDevice()
        {
            DeviceName = "PLC";
            OpenDevice();
            Master = MasterFactory.CreateSerialMaster(_port, MASTER_PROTROL.MODBUS);
        }

    }

    public class LeakageDevice1 : LeakageDevice
    {
        public static readonly LeakageDevice1 instance = new LeakageDevice1();
        private LeakageDevice1()
        {
            DeviceName = "LeakageDevice1";
            OpenDevice();
        }      
    }
    public class LeakageDevice2 : LeakageDevice
    {
        public static readonly LeakageDevice2 instance = new LeakageDevice2();
        private LeakageDevice2()
        {
            DeviceName = "LeakageDevice2";
            OpenDevice();
        }
    }
    public class LeakageDevice3 : LeakageDevice
    {
        public static readonly LeakageDevice3 instance = new LeakageDevice3();
        private LeakageDevice3()
        {
            DeviceName = "LeakageDevice3";
            OpenDevice();
        }
    }
    public class LeakageDevice4 : LeakageDevice
    {
        public static readonly LeakageDevice4 instance = new LeakageDevice4();
        private LeakageDevice4()
        {
            DeviceName = "LeakageDevice4";
            OpenDevice();
        }
    }

    public class LeakageDevice:SerialDevice
    {
        public bool ChangeProduct(int i)
        {
            try
            {
                string CMD = string.Format("*RCL {0}\n", i);
                _port.Write("*IDN?\n");
                _port.Write(CMD);
                return true;
            }
            catch (Exception ex)
            {
                return false;
               // throw;
            }
        }
    }
    public class SerialDevice
    {
        private const string ConnectionString = "Data Source=Config/config.db;Version=3;";
        public SerialPort _port = new SerialPort();
        private Encoding _encoding = Encoding.UTF8;
        /// <summary>
        /// 串口使用的字符编码
        /// </summary>
        public Encoding Encoding
        {
            get { return _encoding; }
            set { _encoding = value; }
        }

        public bool IsOpen { get { return _port.IsOpen; } }
        /// <summary>
        /// 读取当前设备串口的配置
        /// </summary>
        /// <returns>串口配置</returns>
        public SerialConfig getCurrentConfig()
        {
            SerialConfig cfg = new SerialConfig();
            cfg.Name =DeviceName;
            cfg.COM = _port.PortName;
            cfg.Baud = _port.BaudRate.ToString();
            cfg.Parity = _port.Parity.ToString();
            switch (_port.StopBits)
            {
                case StopBits.None:
                    cfg.Stopbits = "0";
                    break;
                case StopBits.One:
                    cfg.Stopbits = "1";
                    break;
                case StopBits.OnePointFive:
                    cfg.Stopbits = "1.5";
                    break;
                case StopBits.Two:
                    cfg.Stopbits = "2";
                    break;
            }
            cfg.Databits = _port.DataBits.ToString();
            return cfg;
        }
        public string DeviceName { get; set; }

        /// <summary>
        /// 打开设备
        /// </summary>
        /// <returns></returns>
        public virtual bool OpenDevice()
        {

            SerialConfig cfg = GetConfigFromDB();
            try
            {
                if (_port.IsOpen)
                {
                    _port.Close();
                }
                _port.PortName = cfg.COM;
                _port.BaudRate = int.Parse(cfg.Baud);
                switch (cfg.Stopbits)
                {
                    case "1":
                        _port.StopBits = StopBits.One;
                        break;
                    case "0":
                        _port.StopBits = StopBits.None;
                        break;
                    case "1.5":
                        _port.StopBits = StopBits.OnePointFive;
                        break;
                    case "2":
                        _port.StopBits = StopBits.Two;
                        break;
                    default:
                        throw new InvalidCastException("Stopbits config is invalid");
                }
                _port.DataBits = int.Parse(cfg.Databits);
                _port.Parity = (Parity)Enum.Parse(typeof(Parity), cfg.Parity);
                _port.Open();
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        /// <returns></returns>
        public virtual bool CloseDevice()
        {
            try
            {
                _port.Close();
                return true;
            }
            catch (Exception)
            {

                return false;
                //  throw;
            }
        }
        /// <summary>
        /// 从数据库中读取配置
        /// </summary>
        /// <returns></returns>
        public SerialConfig GetConfigFromDB()
        {
            var _dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqliteDialect.Provider);
            using (var db = _dbFactory.OpenDbConnection())
            {
                if (db.CreateTableIfNotExists<SerialConfig>())
                {

                }
                if (!db.Exists<SerialConfig>(t => t.Name == DeviceName))
                {
                    db.Insert<SerialConfig>(new SerialConfig(DeviceName + ",COM3,9600,8,1,None"));
                }
                return db.Single<SerialConfig>(x => x.Name == DeviceName);
            }
        }
        /// <summary>
        /// 将配置更新到数据库
        /// </summary>
        /// <param name="cfg"></param>
        public void SetConfig(SerialConfig cfg)
        {
            var _dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqliteDialect.Provider);
            using (var db = _dbFactory.OpenDbConnection())
            {
                db.CreateTableIfNotExists<SerialConfig>();
                if (!db.Exists<SerialConfig>(t => t.Name == DeviceName))
                {
                    db.Insert<SerialConfig>(cfg);
                }
                else
                {
                    db.Update<SerialConfig>(cfg);
                }
            }
        }
        /// <summary>
        /// 发送并等待返回
        /// </summary>
        /// <param name="cmd">命令</param>
        /// <param name="Expect">期望的字符串</param>
        /// <param name="timeout">占用的时间</param>
        /// <returns></returns>
        public string Request(string cmd, string Expect="\n", int timeout = 1000)
        {
            _port.Write(cmd);
            Stopwatch sw = new Stopwatch();
            string recv = "";
            sw.Start();
            while (sw.ElapsedMilliseconds < timeout)
            {
                if (_port.BytesToRead > 0)
                {
                    byte[] _data = new byte[_port.BytesToRead];
                    _port.Read(_data, 0, _data.Length);
                    recv += _encoding.GetString(_data).Trim();
                    if (recv.Contains(Expect))
                        break;
                }
                Application.DoEvents();
            }
            return recv;
        }

    }
}
